<?php

namespace app\api\controller;

use app\common\controller\Frontend;
use app\common\library\Auth;
use app\common\model\enneagram\Results;
use app\common\model\Order;
use app\common\model\RedemptionCode as RedemptionCodeModel;
use app\common\model\RedemptionCodeUsage;
use app\common\model\User;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\exception\ValidateException;
use think\Response;

/**
 * 兑换码接口
 */
class RedemptionCode extends Frontend
{
    protected array $noNeedLogin = [];
    protected array $noNeedRight = ['*'];

    /**
     * 验证兑换码
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function verify(): void
    {
        $code = $this->request->param('code', '');

        if (empty($code)) {
            $this->error('请输入兑换码');
        }

        $redemptionCode = RedemptionCodeModel::where('code', $code)->find();

        if (!$redemptionCode) {
            $this->error('兑换码不存在');
        }
        // 检查是否达到最大使用次数
        if ($redemptionCode->used_count >= $redemptionCode->max_uses) {
            $this->error('兑换码使用次数已达上限');
        }

        if ($redemptionCode->isExpired()) {
            $this->error('兑换码未在有效期内');
        }
        // 使用常量检查状态
        if ($redemptionCode->status != RedemptionCodeModel::STATUS_ACTIVE) {
            $this->error('兑换码不可用');
        }




        // 如果用户已登录，检查是否已使用过此兑换码
        $auth = Auth::instance();
        if ($auth->isLogin()) {
            $user = $auth->getUser();

            $existingUsage = RedemptionCodeUsage::where('code_id', $redemptionCode->id)
                ->where('user_id', $user->id)
                ->find();

            if ($existingUsage) {
                $this->error('您已使用过此兑换码');
            }
        }

        $this->success('兑换码验证成功', [
            'code' => $redemptionCode->code,
            'type' => $redemptionCode->type,
            'description' => $redemptionCode->description,
        ]);
    }

    /**
     * 使用兑换码
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     * @throws Exception
     */
    public function use(): void
    {
        $code = $this->request->param('code', '');
        $resultId = $this->request->param('result_id', 0); // 关联报告ID

        if (empty($code)) {
            $this->error('请输入兑换码');
        }

        if (empty($resultId)) {
            $this->error('缺少报告ID');
        }

        $auth = Auth::instance();
        if (!$auth->isLogin()) {
            $this->error('请先登录');
        }

        $user = $auth->getUser();
        $redemptionCode = RedemptionCodeModel::where('code', $code)->find();

        if (!$redemptionCode) {
            $this->error('兑换码不存在');
        }

        // 使用常量检查状态
        if ($redemptionCode->status != RedemptionCodeModel::STATUS_ACTIVE) {
            $this->error('兑换码不可用');
        }

        if ($redemptionCode->isExpired()) {
            $this->error('兑换码未在有效期内');
        }

        // 检查是否达到最大使用次数
        if ($redemptionCode->used_count >= $redemptionCode->max_uses) {
            $this->error('兑换码使用次数已达上限');
        }

        // 对于单次使用的兑换码，检查用户是否已使用过
        $existingUsage = RedemptionCodeUsage::where('code_id', $redemptionCode->id)
            ->where('user_id', $user->id)
            ->find();

        if ($existingUsage) {
            $this->error('您已使用过此兑换码');
        }

        // 验证报告是否存在且属于当前用户
        $result = Results::where('id', $resultId)->find();
        if (!$result) {
            $this->error('报告不存在');
        }
        if (!$result->order_id) {
            $this->error('报告未关联订单');
        }

        // 开启事务处理兑换码使用
        \think\facade\Db::startTrans();
        try {
            // 使用兑换码，传入result_id作为关联ID
            $useResult = $redemptionCode->use($user->id, $result->order_id, $resultId);

            if ($useResult) {
                // 直接更新报告支付状态
                Results::update([
                    'pay_status' => Results::PAY_STATUS_PAID,
                    'update_time' => time()
                ], ['id' => $resultId]);

                // 查找是否存在相关订单，如果存在则更新订单状态
                $order = Order::find($result->order_id);
                if ($order) {
                    $order->save([
                        'redemption_code_id' => $redemptionCode->id,
                        'redemption_code' => $redemptionCode->code,
                        'acquisition_type' => Order::ACQUISITION_TYPE_REDEMPTION,
                        'pay_status' => Order::PAY_STATUS_PAID, // 兑换码使用后视为已支付
                        'paid_at' => date('Y-m-d H:i:s', time()),
                        'update_time' => time(),
                    ]);
                }

                \think\facade\Db::commit();

                $this->success('兑换码使用成功', [
                    'code' => $redemptionCode->code,
                    'type' => $redemptionCode->type,
                    'discount_amount' => $redemptionCode->discount_amount,
                    'discount_percent' => $redemptionCode->discount_percent,
                    'description' => $redemptionCode->description,
                    'result_id' => $resultId,
                ]);
            } else {
                \think\facade\Db::rollback();
                $this->error('兑换码使用失败');
            }
        } catch (Exception $e) {
            \think\facade\Db::rollback();
            $this->error($e->getMessage());
        }
    }

    /**
     * 获取用户兑换码使用记录
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function history(): void
    {
        $auth = Auth::instance();
        if (!$auth->isLogin()) {
            $this->error('请先登录');
        }

        $user = $auth->getUser();
        $page = $this->request->param('page', 1);
        $limit = $this->request->param('limit', 10);

        $records = RedemptionCodeUsage::where('user_id', $user->id)
            ->with(['redemption_code'])
            ->order('used_at desc')
            ->paginate([
                'list_rows' => $limit,
                'page' => $page
            ]);

        $list = [];
        foreach ($records->items() as $record) {
            $list[] = [
                'code' => $record->code,
                'type' => $record->type,
                'type_text' => $record->redemption_code ? $record->redemption_code->getTypeTextAttr() : '',
                'value' => $record->value,
                'used_at' => date('Y-m-d H:i:s', $record->used_at),
                'description' => $record->redemption_code ? $record->redemption_code->description : '',
            ];
        }

        $this->success('获取成功', [
            'list' => $list,
            'total' => $records->total(),
            'page' => $page,
            'limit' => $limit,
        ]);
    }

    /**
     * 批量验证兑换码（用于支付页面）
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function batchVerify(): void
    {
        $codes = $this->request->param('codes', []);

        if (empty($codes) || !is_array($codes)) {
            $this->error('请提供兑换码列表');
        }

        $results = [];
        $totalValue = 0;
        $validCodes = [];
        $invalidCodes = [];

        foreach ($codes as $code) {
            $redemptionCode = RedemptionCodeModel::where('code', $code)->find();

            if (!$redemptionCode) {
                $invalidCodes[] = [
                    'code' => $code,
                    'valid' => false,
                    'message' => '兑换码不存在',
                ];
                continue;
            }

            // 使用常量检查状态
            if ($redemptionCode->status != RedemptionCodeModel::STATUS_ACTIVE) {
                $invalidCodes[] = [
                    'code' => $code,
                    'valid' => false,
                    'message' => '兑换码不可用',
                ];
                continue;
            }

            if ($redemptionCode->isExpired()) {
                $invalidCodes[] = [
                    'code' => $code,
                    'valid' => false,
                    'message' => '兑换码未在有效期内',
                ];
                continue;
            }

            // 检查是否达到最大使用次数
            if ($redemptionCode->used_count >= $redemptionCode->max_uses) {
                $invalidCodes[] = [
                    'code' => $code,
                    'valid' => false,
                    'message' => '兑换码使用次数已达上限',
                ];
                continue;
            }

            // 如果用户已登录，检查是否已使用过
            $auth = Auth::instance();
            if ($auth->isLogin()) {
                $user = $auth->getUser();

                // 对于单次使用的兑换码，检查用户是否已使用过
                if ($redemptionCode->type == RedemptionCodeModel::TYPE_SINGLE) {
                    $existingUsage = RedemptionCodeUsage::where('code_id', $redemptionCode->id)
                        ->where('user_id', $user->id)
                        ->find();

                    if ($existingUsage) {
                        $invalidCodes[] = [
                            'code' => $code,
                            'valid' => false,
                            'message' => '您已使用过此兑换码',
                        ];
                        continue;
                    }
                }
            }

            // 验证通过的兑换码
            $validCodes[] = [
                'code' => $code,
                'valid' => true,
                'type' => $redemptionCode->type,
                'type_text' => $redemptionCode->getTypeTextAttr(),
                'value' => $redemptionCode->value,
                'discount_amount' => $redemptionCode->discount_amount,
                'discount_percent' => $redemptionCode->discount_percent,
                'description' => $redemptionCode->description,
                'message' => '验证成功',
            ];

            $totalValue += $redemptionCode->value;
        }

        $this->success('批量验证完成', [
            'valid_codes' => $validCodes,
            'invalid_codes' => $invalidCodes,
            'total_value' => $totalValue,
            'valid_count' => count($validCodes),
            'invalid_count' => count($invalidCodes),
        ]);
    }
}
